// mgxdao_test.go
package mgxdao

import (
	"fmt"
	"testing"
)

var testOrm *MgxOrm

func setupTestDBT(t *testing.T) {
	// 方案 B: MySQL（推荐）
	orm := &MgxOrm{}
	if err := orm.OpenEx("mysql", "root", "Mgx780707Mgx", "127.0.0.1", "3306", "test", "utf8"); err != nil {
		t.Fatalf("无法连接测试数据库: %v", err)
	}

	// 创建测试表
	_, err := orm.Exec(`DROP TABLE IF EXISTS user_test`)
	if err != nil {
		t.Fatal(err)
	}
	_, err = orm.Exec(`CREATE TABLE user_test (
		id INT AUTO_INCREMENT PRIMARY KEY,
		name VARCHAR(50),
		pass VARCHAR(50),
		age INT
	) ENGINE=InnoDB DEFAULT CHARSET=gbk`)
	if err != nil {
		t.Fatal(err)
	}

	// 插入测试数据
	for i := 1; i <= 100; i++ {
		_, err = orm.Exec("INSERT INTO user_test (name, pass, age) VALUES (?, ?, ?)",
			fmt.Sprintf("user%03d", i), "123456", 20+i%30)
		if err != nil {
			t.Fatal(err)
		}
	}

	testOrm = orm
}
func setupTestDBB(t *testing.B) {
	// 方案 B: MySQL（推荐）
	orm := &MgxOrm{}
	if err := orm.OpenEx("mysql", "root", "Mgx780707Mgx", "127.0.0.1", "3306", "test", "utf8"); err != nil {
		t.Fatalf("无法连接测试数据库: %v", err)
	}

	// 创建测试表
	_, err := orm.Exec(`DROP TABLE IF EXISTS user_test`)
	if err != nil {
		t.Fatal(err)
	}
	_, err = orm.Exec(`CREATE TABLE user_test (
		id INT AUTO_INCREMENT PRIMARY KEY,
		name VARCHAR(50),
		pass VARCHAR(50),
		age INT
	) ENGINE=InnoDB DEFAULT CHARSET=gbk`)
	if err != nil {
		t.Fatal(err)
	}

	// 插入测试数据
	for i := 1; i <= 100; i++ {
		_, err = orm.Exec("INSERT INTO user_test (name, pass, age) VALUES (?, ?, ?)",
			fmt.Sprintf("user%03d", i), "123456", 20+i%30)
		if err != nil {
			t.Fatal(err)
		}
	}

	testOrm = orm
}
func setupTestDB(t *testing.T) {
	// 方案 B: MySQL（推荐）
	orm := &MgxOrm{}
	if err := orm.OpenEx("mysql", "root", "Mgx780707Mgx", "127.0.0.1", "3306", "test", "utf8"); err != nil {
		t.Fatalf("无法连接测试数据库: %v", err)
	}

	// 创建测试表
	_, err := orm.Exec(`DROP TABLE IF EXISTS user_test`)
	if err != nil {
		t.Fatal(err)
	}
	_, err = orm.Exec(`CREATE TABLE user_test (
		id INT AUTO_INCREMENT PRIMARY KEY,
		name VARCHAR(50),
		pass VARCHAR(50),
		age INT
	) ENGINE=InnoDB DEFAULT CHARSET=gbk`)
	if err != nil {
		t.Fatal(err)
	}

	// 插入测试数据
	for i := 1; i <= 100; i++ {
		_, err = orm.Exec("INSERT INTO user_test (name, pass, age) VALUES (?, ?, ?)",
			fmt.Sprintf("user%03d", i), "123456", 20+i%30)
		if err != nil {
			t.Fatal(err)
		}
	}

	testOrm = orm
}

func teardownTestDBT(t *testing.T) {
	if testOrm != nil {
		testOrm.Exec("DROP TABLE IF EXISTS user_test")
		testOrm.Close()
	}
}
func teardownTestDBB(t *testing.B) {
	if testOrm != nil {
		testOrm.Exec("DROP TABLE IF EXISTS user_test")
		testOrm.Close()
	}
}

// ========== 单元测试 ==========

func TestQueryOne(t *testing.T) {
	setupTestDB(t)
	defer teardownTestDBT(t)

	var user User
	err := testOrm.QueryOne(&user, "SELECT * FROM user_test WHERE id = ?", 1)
	if err != nil {
		t.Fatalf("QueryOne failed: %v", err)
	}
	if user.Id != 1 || user.Name != "user001" {
		t.Errorf("Expected user001, got %+v", user)
	}
}

func TestQuery(t *testing.T) {
	setupTestDB(t)
	defer teardownTestDBT(t)

	var users []User
	err := testOrm.Query(&users, "SELECT * FROM user_test WHERE age > ? ORDER BY id LIMIT 10", 30)
	if err != nil {
		t.Fatalf("Query failed: %v", err)
	}
	if len(users) != 10 {
		t.Errorf("Expected 10 users, got %d", len(users))
	}
}

func TestSaveAndUpdate(t *testing.T) {
	setupTestDB(t)
	defer teardownTestDBT(t)

	// Save
	id, err := testOrm.SaveObjectEx("user_test", User{Name: "newuser", Pass: "pass", Age: 25})
	if err != nil {
		t.Fatalf("SaveObjectEx failed: %v", err)
	}
	if id <= 100 {
		t.Errorf("Expected new ID > 100, got %d", id)
	}

	// Update
	user := User{Id: int(id), Name: "updated", Pass: "newpass", Age: 30}
	_, err = testOrm.UpdateObject(user, "user_test", "id")
	if err != nil {
		t.Fatalf("UpdateObject failed: %v", err)
	}

	// Verify
	var u User
	testOrm.QueryOne(&u, "SELECT * FROM user_test WHERE id = ?", id)
	if u.Name != "updated" || u.Age != 30 {
		t.Errorf("Update failed, got %+v", u)
	}
}

// ========== 基准测试 ==========

func BenchmarkQueryOne_Cached(b *testing.B) {
	setupTestDBB(b)
	defer teardownTestDBB(b)

	var user User
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		// 每次查不同ID，但结构体类型相同 → 字段缓存命中
		testOrm.QueryOne(&user, "SELECT * FROM user_test WHERE id = ?", (i%100)+1)
	}
}

func BenchmarkQuery_Cached(b *testing.B) {
	setupTestDBB(b)
	defer teardownTestDBB(b)

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		var users []User
		testOrm.Query(&users, "SELECT * FROM user_test LIMIT 10")
	}
}

// 对比：如果你有“旧版”未优化的 MgxOrm，可命名为 MgxOrmOld，做对比
// func BenchmarkQueryOld(b *testing.B) { ... }
type User struct {
	Id   int    `mgx:"id"`
	Name string `mgx:"name"`
	Pass string `mgx:"pass"`
	Age  int    `mgx:"age"`
}
